using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Audio;
using UnityEngine.Playables;
using UnityEngine.Timeline;

public class VSkillDefine { }

[Serializable]
public class VSkillPack
{
    public string skillName;
    public string skillDescription;
    public TimelineAsset timeline;
    public List<TimelineClip> CollectClips()
    {
        var collection = new List<TimelineClip>(50);
        foreach (var track in timeline.GetRootTracks())
        {
            if (!track.muted)
            {
                collection.AddRange(track.GetClips());
            }
        }
        return collection;
    }
}
public class VSkillStateGraphBase
{
    public string graphName;
    public GameObject attatchedObject;
    public PlayableGraph baseGraph;
    public virtual void InitGraph() { }
    public void print(object o)
    {
        Debug.Log(o);
    }
    ~VSkillStateGraphBase()
    {
        if (baseGraph.IsValid())
            baseGraph.Destroy();
    }
    public void Destroy()
    {
        if (baseGraph.IsValid())
        {
            baseGraph.Destroy();
            _Destory();
        }
    }
    public virtual void _Destory() { }
    public TimelineClip lastTmlClip;
    public void Play(TimelineClip timelineClip)
    {
        lastTmlClip = timelineClip;
        _Play(timelineClip);
    }
    public virtual void _Play(TimelineClip timelineClip) { }
    public virtual bool Complete() => false;
    public void EndLast() { if (lastTmlClip != null) _Endlast(); }
    public virtual void _Endlast() => Debug.Log("子类没有实现Endlast的重载");
    public void Stop()
    {
        if (baseGraph.IsValid())
        {
            baseGraph.Stop();
        }
    }
    public void PlayGraph()
    {
        if (baseGraph.IsValid())
        {
            baseGraph.Play();
        }
    }
}


//单层图备份
public class VS_AnimationGraph : VSkillStateGraphBase
{
    public AnimationClipPlayable[] fusionclipStack = new AnimationClipPlayable[stackTop]; //那么其实这个栈底应该从1 开始 , 因为需要留一个基础idle动作
    private int stackIndex = stackBottom;
    private const int stackBottom = 1;
    private const int stackTop = 4;
    public AnimationPlayableOutput output;
    public AnimationMixerPlayable mixer;
    //由于动作混合需要保留前一个动作的姿态, 所以至少有两个口用来混合一个clip
    TObserver TOB_clipEndChecker;

    public Action onTransDefault;
    public Action<AnimationClip> onExitAnimation;
    public override void InitGraph()
    {
        baseGraph = PlayableGraph.Create(graphName);
        output = AnimationPlayableOutput.Create(baseGraph, $"{attatchedObject}-{graphName}", attatchedObject.GetComponentInChildren<Animator>());
        mixer = AnimationMixerPlayable.Create(baseGraph, stackTop);
        output.SetSourcePlayable(mixer);
        if (Application.isPlaying)
            baseGraph.Play();
    }
    public void ForceInitGraph()
    {
        baseGraph.Play();
    }
    public VS_AnimationGraph(GameObject go, string name = "AnimationGraph")
    {
        graphName = go.name + name;
        attatchedObject = go;
        InitGraph();
    }
    public void SetDefaultAnimation(AnimationClip defaultClip)
    {
        //默认动画的占位符是0  , 这里先设置权重为1
        var dClip = AnimationClipPlayable.Create(baseGraph, defaultClip);
        fusionclipStack[0] = dClip;
        baseGraph.Connect(fusionclipStack[0], 0, mixer, 0);
        SetMixerWeight(0, 1);
    }

    public AnimationClip lastContinueClip;
    private int lastWrtiePort = 1; //就是一个上下的开关位 1or2
    private int curWritePort
    {
        get
        {
            lastWrtiePort = lastWrtiePort == 1 ? 2 : 1;
            return lastWrtiePort;
        }
    }
    public bool ContinueAnimationClip(AnimationClip clip)
    {
        int port = -1;
        if (lastContinueClip == clip)
        {
            port = lastWrtiePort;
            ObserverAdd_TransWeightTo(port);
            return true;
        }
        else
        {
            //什么时候销毁?
            port = curWritePort;
            if (StackValidate(port))
            {
                fusionclipStack[port].Destroy();
                onExitAnimation?.Invoke(lastContinueClip);
            }
            baseGraph.Disconnect(mixer, port);
            WeightBalanceObserver?.Cancel();
            TOB_clipEndChecker?.Cancel();
        }
        var c = AnimationClipPlayable.Create(baseGraph, clip);
        lastContinueClip = clip;
        baseGraph.Connect(c, 0, mixer, port);
        mixer.SetInputWeight(port, 0); //保证新连上去的为0
        fusionclipStack[port] = c;
        ObserverAdd_TransWeightTo(port);
        return false;
    }
    public void TriggerAnimationClip(AnimationClip clip, Action end = null)
    {
        int port = -1;
        if (lastContinueClip == clip)
        {
            port = lastWrtiePort;
            fusionclipStack[port].SetTime(0);
            ObserverAdd_TransWeightTo(port);
            ObserverAdd_OnClipEnd(clip, TransDefault + end);
            return;
        }
        else
        {
            //什么时候销毁?
            port = curWritePort;
            if (StackValidate(port)) fusionclipStack[port].Destroy();
            baseGraph.Disconnect(mixer, port);
            WeightBalanceObserver?.Cancel();
            TOB_clipEndChecker?.Cancel();
        }
        var c = AnimationClipPlayable.Create(baseGraph, clip);
        lastContinueClip = clip;
        baseGraph.Connect(c, 0, mixer, port);
        mixer.SetInputWeight(port, 0); //保证新连上去的为0
        fusionclipStack[port] = c;
        ObserverAdd_TransWeightTo(port);
        ObserverAdd_OnClipEnd(clip, TransDefault + end);
    }
    public void SetClip(AnimationClip clip, int port)
    {
        if (fusionclipStack[port].IsValid())
        {
            fusionclipStack[port].Destroy();
            baseGraph.Disconnect(mixer, port);
        }
        TOB_clipEndChecker?.Cancel();

        if (clip == null)
        {
            mixer.SetInputWeight(port, 0);
            return;
        }
        var c = AnimationClipPlayable.Create(baseGraph, clip);
        baseGraph.Connect(c, 0, mixer, port);
        mixer.SetInputWeight(port, 1); //debug直接设为1
        fusionclipStack[port] = c;

    }
    //这里统一加了启用时不生效的限制,保证启动唯一性
    public TObserver WeightBalanceObserver;
    public int curBalancePort = 0;
    /// <summary>
    /// 全图的动画输出权重必须保证和为1 , 不多不少
    /// </summary>
    /// <param name="port">mixer端口 </param>
    /// <param name="duration">持续时间 </param>
    public void ObserverAdd_TransWeightTo(int port, float duration = 0.3f)
    {
        if (port == -1) return;
        if (WeightBalanceObserver.Validate() && curBalancePort == port) return;
        if (mixer.GetInputWeight(port) > 0.95f) return;
        float[] weights = new float[]
        {
             mixer.GetInputWeight(0),
             mixer.GetInputWeight(1),
             mixer.GetInputWeight(2),
             mixer.GetInputWeight(3),
        };
        float startTime = Time.time;
        curBalancePort = port;
        if (StackValidate(port)) fusionclipStack[port].SetTime(0);
        WeightBalanceObserver = new TObserver()
        {
            name = "WeightBalanceObserver",
            duration = duration,
            tick = () =>
            {
                float ratio = (Time.time - startTime) / duration;
                for (int i = 0; i < 4; i++)
                    if (i == port) mixer.SetInputWeight(i, Mathf.Lerp(weights[i], 1, ratio));
                    else mixer.SetInputWeight(i, Mathf.Lerp(weights[i], 0, ratio));
            },
            end = () =>
            {
                for (int i = 0; i < 4; i++)
                {
                    if (i == port) mixer.SetInputWeight(i, 1);
                    else
                    {
                        mixer.SetInputWeight(i, 0);
                        //if (StackValidate(i)) fusionclipStack[i].SetTime(0);
                    }
                }
                if (port == 0)
                    onTransDefault?.Invoke();
            }
        }.Subscribe();
    }
    private void ObserverAdd_OnClipEnd(AnimationClip clip, Action onEnd)
    {
        TOB_clipEndChecker = new TObserver()
        {
            name = "播放后回归到default",
            duration = clip.averageDuration,
            end = onEnd
        }.Subscribe();
    }
    public void SetDefault() => ObserverAdd_TransWeightTo(0, 0);
    public void TransDefault() => ObserverAdd_TransWeightTo(0);
    private bool StackValidate(int port) => (!fusionclipStack[port].IsNull()) && fusionclipStack[port].IsValid();
    public void Evaluate(int port, double time)
    {
        if (!fusionclipStack[port].IsNull() && fusionclipStack[port].IsValid())
        {
            fusionclipStack[port].SetTime(time);
            baseGraph.Evaluate();
        }
    }
    public void ClearStack()
    {
        for (int i = stackBottom; i < stackIndex; i++)
        {
            //是不是应该先断联 -->对图是不用的
            mixer.SetInputWeight(i, 0);
            fusionclipStack[i].Destroy();
        }
        stackIndex = stackBottom;
        mixer.SetInputWeight(stackBottom, 1);
    }
    private void SetMixerWeight(int port, float weight)
    {
        float sideWeight = 1 - weight;
        for (int i = 0; i < stackTop; i++)
        {
            mixer.SetInputWeight(i, sideWeight);
        }
        mixer.SetInputWeight(port, weight);
    }
    public override void _Play(TimelineClip timelineClip)
    {
        var c = timelineClip.ToBehavior().AnimationHandler_Data.clip;
        ContinueAnimationClip(c);
    }
    public override void _Endlast()
    {
        TransDefault();
    }
}
public class VS_EntityGraph : VSkillStateGraphBase
{
    public ScriptPlayableOutput output;
    public override void InitGraph()
    {
        baseGraph = PlayableGraph.Create(graphName);
        output = ScriptPlayableOutput.Create(baseGraph, $"{attatchedObject}-{graphName}");
        baseGraph.Play();
    }

    public VS_EntityGraph(GameObject go, string name = "VS_EntityGraph")
    {
        graphName = go.name + name;
        attatchedObject = go;
        InitGraph();
    }
    private Playable lastPlayable;
    public void PlayHitCollider(TimelineClip timelineClip)
    {
        var vsClip = timelineClip.asset as VSBasicClip;
        lastPlayable = vsClip.CreatePlayableManual(baseGraph, attatchedObject);
        output.SetSourcePlayable(lastPlayable);
    }
    public override void _Play(TimelineClip timelineClip)
    {
        PlayHitCollider(timelineClip);
    }
    public override void _Endlast()
    {
        lastPlayable.Destroy();
    }
}

public class VS_VacancyGraph : VSkillStateGraphBase
{
    public ScriptPlayableOutput output;
    public override void InitGraph()
    {
        baseGraph = PlayableGraph.Create(graphName);
        output = ScriptPlayableOutput.Create(baseGraph, $"{attatchedObject}-{graphName}");
        baseGraph.Play();
    }
    public VS_VacancyGraph(GameObject go, string name = "VS_VacancyGraph")
    {
        graphName = go.name + name;
        attatchedObject = go;
        InitGraph();
    }
    private Playable lastPlayable;
    public void PlayVacancy(TimelineClip timelineClip)
    {
        var vsClip = timelineClip.asset as VSBasicClip;
        lastPlayable = vsClip.CreatePlayableManual(baseGraph, attatchedObject);
        output.SetSourcePlayable(lastPlayable);
    }
    public override void _Play(TimelineClip timelineClip)
    {
        PlayVacancy(timelineClip);
    }

    public override void _Endlast()
    {
        lastPlayable.Destroy();
    }
}

public class VS_ControlGraph : VSkillStateGraphBase
{
    public ScriptPlayableOutput output;
    public override void InitGraph()
    {
        baseGraph = PlayableGraph.Create(graphName);
        output = ScriptPlayableOutput.Create(baseGraph, $"{attatchedObject}-{graphName}");
        baseGraph.Play();
    }
    public VS_ControlGraph(GameObject go, string name = "VS_ScriptGraph")
    {
        graphName = go.name + name;
        attatchedObject = go;
        InitGraph();
    }

    private Playable lastPlayable;
    public override void _Play(TimelineClip timelineClip)
    {
        var vsClip = timelineClip.asset as VSBasicClip;
        lastPlayable = vsClip.CreatePlayableManual(baseGraph, attatchedObject);
        output.SetSourcePlayable(lastPlayable);
    }
    public override void _Endlast()
    {
        lastPlayable.Destroy();
    }

}

public class VS_InteractGraph : VSkillStateGraphBase
{
    public ScriptPlayableOutput output;
    public override void InitGraph()
    {
        baseGraph = PlayableGraph.Create(graphName);
        output = ScriptPlayableOutput.Create(baseGraph, $"{attatchedObject}-{graphName}");
        baseGraph.Play();
    }
    public VS_InteractGraph(GameObject go, string name = "VS_InteractGraph")
    {
        graphName = go.name + name;
        attatchedObject = go;
        InitGraph();
    }
    private Playable lastPlayable;
    public override void _Play(TimelineClip timelineClip)
    {
        var vsClip = timelineClip.asset as VSBasicClip;
        lastPlayable = vsClip.CreatePlayableManual(baseGraph, attatchedObject);
        output.SetSourcePlayable(lastPlayable);
    }
    public Func<bool> onInteract;
    public override bool Complete() => onInteract == null ? false : onInteract.Invoke();

    public override void _Endlast()
    {
        lastPlayable.Destroy();
    }
}


public class VS_AudioGraph : VSkillStateGraphBase
{
    public AudioPlayableOutput output;
    public override void InitGraph()
    {
        baseGraph = PlayableGraph.Create(graphName);
        var audioSource = attatchedObject.UniqueComponent<AudioSource>();
        output = AudioPlayableOutput.Create(baseGraph, $"{attatchedObject}-{graphName}", audioSource);
        baseGraph.Play();
    }
    public VS_AudioGraph(GameObject go, string name = "VS_AudioGraph")
    {
        graphName = go.name + name;
        attatchedObject = go;
        InitGraph();
    }
    private Playable lastPlayable;
    public override void _Play(TimelineClip timelineClip)
    {
        var data = timelineClip.ToBehavior().AudioHandler_Data;
        // lastPlayable = vsClip.CreatePlayableManual(baseGraph, attatchedObject);
        lastPlayable = AudioClipPlayable.Create(baseGraph, data.audioClip, data.looping);
        output.SetSourcePlayable(lastPlayable);
    }
    public override void _Endlast()
    {
        lastPlayable.Destroy();
    }
    public void PlayAudio(AudioClip audioClip, bool looping = false)
    {
        lastPlayable = AudioClipPlayable.Create(baseGraph, audioClip, looping);
        output.SetSourcePlayable(lastPlayable);
    }
}




////这个是IKPose多层的重置版本,但是现在没时间调这个, 先用原版
public class VS_MulitPassAnimationGraph : VSkillStateGraphBase
{
    public AnimationClipPlayable[] basePoseClipStack = new AnimationClipPlayable[2]; //basePoseMixer管理两个
    public AnimationPlayableOutput output;
    // 0: idle层级 1:基础动作层级 2:Avatar层级 3:IK层级
    public AnimationLayerMixerPlayable layerMixer;
    //由于动作混合需要保留前一个动作的姿态, 所以至少有两个口用来混合一个clip
    TObserver TOB_clipEndChecker;

    public Action onTransDefault;
    public Action<AnimationClip> onExitAnimation;
    private AnimationMixerPlayable idlePoseMixer;
    private AnimationMixerPlayable basePoseMixer;
    private AnimationMixerPlayable avatarPoseMixer;
    private AnimationMixerPlayable[] layers;

    public override void InitGraph()
    {
        baseGraph = PlayableGraph.Create(graphName);
        output = AnimationPlayableOutput.Create(baseGraph, $"{attatchedObject}-{graphName}", attatchedObject.GetComponentInChildren<Animator>());

        layerMixer = AnimationLayerMixerPlayable.Create(baseGraph, 4);

        idlePoseMixer = AnimationMixerPlayable.Create(baseGraph, 3);//支持三种待机动画的混合
        basePoseMixer = AnimationMixerPlayable.Create(baseGraph, 2);//basePose有两种切换 为了保持上次的状态
        avatarPoseMixer = AnimationMixerPlayable.Create(baseGraph, 5);//四肢+head的5个接口

        // layerMixer.SetLayerMaskFromAvatarMask
        //还有一层留给ik , 但是ik是外部控制的, 可能用不到 , 得自己看finalIK了
        layers = new AnimationMixerPlayable[]
        {
            idlePoseMixer,basePoseMixer,avatarPoseMixer
        };
        baseGraph.Connect(idlePoseMixer, 0, layerMixer, 0);
        baseGraph.Connect(basePoseMixer, 0, layerMixer, 1);
        baseGraph.Connect(avatarPoseMixer, 0, layerMixer, 2);
        output.SetSourcePlayable(layerMixer);
        if (Application.isPlaying)
            baseGraph.Play();
    }
    private AnimationClipPlayable avatarTemp;
    public void PlaySingle(AnimationClip clip, VAvatarMaskID mask, bool isContinue = false)
    {
        //单播是可以权重>1 的, 因为遮罩有权重设置
        if (isContinue)
        {

        }
        else
        {
            var clipp = AnimationClipPlayable.Create(baseGraph, clip);
            baseGraph.Disconnect(avatarPoseMixer, 0); //TODO:现在先泄露着吧
            baseGraph.Connect(clipp, 0, avatarPoseMixer, 0);
            avatarPoseMixer.SetInputWeight(0, 1);
            layerMixer.SetLayerAdditive(2, false); //单播的动画就是覆盖的 
            layerMixer.SetLayerMaskFromAvatarMask(2, VAnimationDefine.GetVAvatarMask(mask).runtimeMask);
            layerMixer.SetInputWeight(2, 1); //由于Mask层是完全覆盖的机制,所以直接1不会权重溢出
        }
    }
    public void PlayInControl(AnimationClip clip, VAvatarMaskID mask, bool isContinue = false)
    {
        var full = VAnimationDefine.GetVAvatarMask(VAvatarMaskID.FullBody).runtimeMask;
        full.SetHumanoidBodyPartActive(AvatarMaskBodyPart.RightArm,false);
        if (isContinue)
        {

        }
        else
        {
            var clipp = AnimationClipPlayable.Create(baseGraph, clip);
            baseGraph.Disconnect(avatarPoseMixer, 0); //TODO:现在先泄露着吧
            baseGraph.Connect(clipp, 0, avatarPoseMixer, 0);
            avatarPoseMixer.SetInputWeight(0, 1);
            layerMixer.SetLayerAdditive(2, false); //单播的动画就是覆盖的 
            layerMixer.SetLayerMaskFromAvatarMask(2, full);
            layerMixer.SetInputWeight(2, 1); //由于Mask层是完全覆盖的机制,所以直接1不会权重溢出
        }
    }

    public void Play(AnimationClip clip, bool isContinue = false, Action end = null)
    {
        if (isContinue)
        {
            int port = -1;
            if (lastContinueClip == clip)
            {
                port = lastWrtiePort;
                ObserverAdd_TransWeightTo(port, 0.1f, 1);
                return;
            }
            else
            {
                //什么时候销毁?
                port = curWritePort;
                if (BasePoseStackValidate(port))
                {
                    basePoseClipStack[port].Destroy();
                    onExitAnimation?.Invoke(lastContinueClip);
                }
                baseGraph.Disconnect(basePoseMixer, port);
                WeightBalanceObserver?.Cancel(); //这里要取消是因为下面的ObserverAdd要订阅, 两者的功能是冲突的,所以只能留一个
                TOB_clipEndChecker?.Cancel();
            }
            var c = AnimationClipPlayable.Create(baseGraph, clip);
            lastContinueClip = clip;
            baseGraph.Connect(c, 0, basePoseMixer, port);
            basePoseMixer.SetInputWeight(port, 0); //basePoseClipStack用来存播放的状态来方便索引
            basePoseClipStack[port] = c;
            ObserverAdd_TransWeightTo(port);
        }
        else
        {
            int port = -1;
            if (lastContinueClip == clip)
            {
                port = lastWrtiePort;
                basePoseClipStack[port].SetTime(0);
                ObserverAdd_TransWeightTo(port);
                ObserverAdd_OnClipEnd(clip, TransDefault + end);
                return;
            }
            else
            {
                //什么时候销毁?
                port = curWritePort;
                if (BasePoseStackValidate(port)) basePoseClipStack[port].Destroy();
                baseGraph.Disconnect(layerMixer, port);
                WeightBalanceObserver?.Cancel();
                TOB_clipEndChecker?.Cancel();
            }
            var c = AnimationClipPlayable.Create(baseGraph, clip);
            lastContinueClip = clip;
            baseGraph.Connect(c, 0, layerMixer, port);
            layerMixer.SetInputWeight(port, 0); //保证新连上去的为0
            basePoseClipStack[port] = c;
            ObserverAdd_TransWeightTo(port);
            ObserverAdd_OnClipEnd(clip, TransDefault + end);
        }
    }

    public VS_MulitPassAnimationGraph(GameObject go, string name = "MutiPassAnimationGraph")
    {
        graphName = go.name + name;
        attatchedObject = go;
        InitGraph();
    }
    public void SetDefaultAnimation(AnimationClip defaultClip)
    {
        //新版中默认idleclip的权重是1
        var dClip = AnimationClipPlayable.Create(baseGraph, defaultClip);
        baseGraph.Connect(dClip, 0, idlePoseMixer, 0);
        idlePoseMixer.SetInputWeight(0, 1);
        layerMixer.SetInputWeight(0, 1);//这个是完全的1 了  现在是把LayerMixer上的0层和1层分开了,其实默认就该一直播放0层, 1层无播放时才能不至于空置 尝试一下来
        layerMixer.SetLayerAdditive(1, false); //尝试一下: 基础姿态就是等待被覆盖的, 当basePose层无输入时会自动idle
    }

    public AnimationClip lastContinueClip;
    private int lastWrtiePort = 0; //就是一个上下的开关位 1or2
    private int curWritePort
    {
        get
        {
            lastWrtiePort = lastWrtiePort == 0 ? 1 : 0;
            return lastWrtiePort;
        }
    }
    public TObserver WeightBalanceObserver;
    public int curBalancePort = 0;
    /// <summary>
    /// basePose图的动画输出权重必须保证和为1 , 不多不少
    /// </summary>
    /// <param name="port">mixer端口 </param>
    /// <param name="duration">持续时间 </param>
    public void ObserverAdd_TransWeightTo(int port, float duration = 0.1f, int layer = 1)
    {
        if (port == -1) return;
        if (WeightBalanceObserver.Validate() && curBalancePort == port) return;
        if (basePoseMixer.GetInputWeight(port) > 0.95f) return;
        float[] weights = new float[]
        {
           basePoseMixer.GetInputWeight(0),
           basePoseMixer.GetInputWeight(1),
           basePoseMixer.GetInputWeight(2),
           basePoseMixer.GetInputWeight(3),
        };
        float startTime = Time.time;
        curBalancePort = port;
        if (BasePoseStackValidate(port)) basePoseClipStack[port].SetTime(0);
        WeightBalanceObserver = new TObserver()
        {
            name = "WeightBalanceObserver",
            duration = duration,
            tick = () =>
            {
                float ratio = (Time.time - startTime) / duration;
                SetBaseMixerWeight(port, ratio);
                // for (int i = 0; i < 4; i++)
                //     if (i == port) basePoseMixer.SetInputWeight(i, Mathf.Lerp(weights[i], 1, ratio));
                //     else basePoseMixer.SetInputWeight(i, Mathf.Lerp(weights[i], 0, ratio));
            },
            end = () =>
            {
                SetBaseMixerWeight(port, 1);
                // for (int i = 0; i < 4; i++)
                //     if (i == port) basePoseMixer.SetInputWeight(i, 1);
                //     else basePoseMixer.SetInputWeight(i, 0);
                if (port == 0) onTransDefault?.Invoke();
            }
        }.Subscribe();
    }
    private void ObserverAdd_OnClipEnd(AnimationClip clip, Action onEnd)
    {
        TOB_clipEndChecker = new TObserver()
        {
            name = "播放后回归到default",
            duration = clip.averageDuration,
            end = onEnd
        }.Subscribe();
    }
    public void TransDefault() => ObserverAdd_TransWeightTo(0);
    private bool BasePoseStackValidate(int port) => (!basePoseClipStack[port].IsNull()) && basePoseClipStack[port].IsValid();
    private void SetBaseMixerWeight(int port, float weight)
    {
        float sideWeight = 1 - weight;
        for (int i = 0; i < 2; i++)
        {
            layerMixer.SetInputWeight(i, sideWeight);
        }
        layerMixer.SetInputWeight(port, weight);
    }

    private void SetLayerMixerWeight(int layer, int port, float weight)
    {
        //是否需要保证层之间混合为1 , 层之内确保混合为1是对的
        //AA:不需要, 只有Additive的混合模式需要保证为1 , overWrite模式总是为1的
    }
    public override void _Play(TimelineClip timelineClip)
    {
        var c = timelineClip.ToBehavior().AnimationHandler_Data.clip;
        Play(c);
    }
    public override void _Endlast()
    {
        TransDefault();
    }
}